#include <iostream>
#include <vector>
using namespace std;

/**
 * 给定两个字符串 text1 和 text2，返回这两个字符串的最长 公共子序列 的长度。
 * 如果不存在 公共子序列 ，返回 0 。
 * 一个字符串的 子序列 是指这样一个新的字符串：
 * 它是由原字符串在不改变字符的相对顺序的情况下删除某些字符（也可以不删除任何字符）后组成的新字符串。
 * 例如，"ace" 是 "abcde" 的子序列，但 "aec" 不是 "abcde" 的子序列。
 * 两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
 * 
 * 示例 1：
 * 输入：text1 = "abcde", text2 = "ace" 
 * 输出：3 
 * 解释：最长公共子序列是 "ace" ，它的长度为 3 。
 * 
 * 示例 2：
 * 输入：text1 = "abc", text2 = "abc"
 * 输出：3
 * 解释：最长公共子序列是 "abc" ，它的长度为 3 。
 * 
 * 示例 3：
 * 输入：text1 = "abc", text2 = "def"
 * 输出：0
 * 解释：两个字符串没有公共子序列，返回 0 。
 * 
 * 解题思路：动态规划
 * 
 * 我们假设字符串text1, text2的长度分别为m, n创建一个m + 1行 n + 1列的二维数组dp[m + 1][n + 1]
 * 其中dp[i][j]表示text1[i] 和 text2[j]的最长公共子序列的长度
 * 考虑动态规划的边界情况：
 * 当i = 0时，text1[i]为空，空字符串和任何字符串的最长公共子序列的长度都是0，因此对于任意0 <= j <= n
 * 有dp[0][j] = 0
 * 当j = 0时，text2[j]为空，同理可得对任意0 <= i <= m有dp[i][0] = 0
 * 因此动态规划的边界情况是：当i = 0 或 j = 0时dp[i][j] = 0
 * 
 * 当i > 0且j >0 时考虑dp[i][j]的计算：
 * 当text[i - 1] == text[j - 1]时将这两个相同的字符称为公共字符，考虑text[i -1]和text[j - 1]
 * 的最长公共子序列，在增加一个字符（即公共字符）即可得到text[i]和text[j]的最长公共子序列
 * 因此dp[i][j] = dp[i - 1][j - 1] + 1
 * 
 * 当text[i - 1] != text[j - 1]时考虑以下两项：
 * text[i - 1]和text[j]的最长公共子序列
 * text[i]和text[j - 1]的最长公共子序列
 * 要得到text[i]和text[j]的最长公共子序列,迎娶两项中的最大值
 * 因此dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
 * 
 * 在最后直接返回dp[m][n]即可得到两个字符串的最长公共子序列的大小
 */

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        //首先确定两个字符串的长度，
        int m = static_cast<int>(text1.length());
        int n = static_cast<int>(text2.length());
        //定义一个我们需要的二维数组dp[m + 1][n + 1]
        vector<vector<int>> dp(m + 1, vector<int> (n + 1));
        for(int i = 1; i <= m; i++) {
            //访问字符串i - 1位的字符，其中test1.at()提供了一个边界检查超过边界将会抛出一个异常
            char c1 = text1.at(i - 1);
            for(int j = 1; j <= n; j++) {
                char c2 = text2.at(j - 1);
                //在下面进行遍历并比较
                if(c1 == c2) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                else {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[m][n];
    }
};